#ifndef TCPSERVER_HPP
#define TCPSERVER_HPP
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>

#include "Task.hpp"
#include "ThreadPool.hpp"
#include "log.hpp"

#include "daemon.hpp"

Log lg;

enum
{
  SOCKET_ERR = 2,
  BIND_ERR,
  LISTEN_ERR
};
const int backlog = 5;

class TcpServer
{
public:
  // 构造函数初始化 TcpServer 类
  TcpServer(uint16_t port = defaultport) : listen_sockfd_(-1), port_(port) {}


  void Init()
  {
    // 创建套接字 绑定 监听

    // 套接字创建
    listen_sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sockfd_ < 0)
    {
      lg(FATAL, "create socket error , error message: %s", strerror(errno));
      exit(SOCKET_ERR);
    }
    lg(INFO, "create socket sucess, sockfd:%d", listen_sockfd_);

    int opt = 1;
    setsockopt(listen_sockfd_, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)); // 防止偶发性的服务器无法进行立即重启

    // 绑定
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(port_);
    local.sin_addr.s_addr = INADDR_ANY;

    socklen_t len = sizeof(local);
    if (bind(listen_sockfd_, (sockaddr *)&local, len) < 0)
    {
      lg(FATAL, "bind error , error message: %s", strerror(errno));
      exit(BIND_ERR);
    }

    // 设置监听
    if (listen(listen_sockfd_, backlog) < 0)
    {
      lg(FATAL, "listen error , error message: %s", strerror(errno));
      exit(LISTEN_ERR);
    }
  }

  void Start()
  {
    Daemon();
    signal(SIGPIPE, SIG_IGN);
    ThreadPool<Task>::getInstance()->Start();

    // 获取连接 处理客户端请求

    lg(INFO, "TcpServer start sucess...");
    while (true)
    {
      // 获取连接
      struct sockaddr_in local;
      memset(&local, 0, sizeof(local));
      socklen_t len = sizeof(local);
      int sockfd = accept(listen_sockfd_, (struct sockaddr *)&local, &len);
      if (sockfd < 0)
      {
        lg(WARNING, "accept error , error message: %s", strerror(errno));
        continue;
      }

      uint16_t client_port = ntohs(local.sin_port);
      char ipstr[32];
      inet_ntop(AF_INET, &(local.sin_addr), ipstr, sizeof(ipstr));

      lg(INFO, "accept sucess , sockfd :%d ,client ip :%s ,client port :%d",
         sockfd, ipstr, client_port);

      Task t(sockfd, ipstr, client_port);
      ThreadPool<Task>::getInstance()->Push(t);
    }
  }

  ~TcpServer()
  {
    // 清理操作
    if (listen_sockfd_ != -1)
    { 
      close(listen_sockfd_);
      listen_sockfd_ = -1;
    }
  }

private:
  int listen_sockfd_; // 服务端的监听套接字描述符
  uint16_t port_;     // 服务端的监听端口

protected:
  static const uint16_t defaultport; // 默认端口号
};
const uint16_t TcpServer::defaultport = 8080; // 默认端口号初始化

#endif